﻿using System;
using System.Configuration;
using System.Collections.Generic;
using System.IO;
using System.Management;
using System.Net;
using System.Net.Sockets;
using System.Text;

namespace EventLogReaderService
{
    internal static class EventLogReader
    {

        private static StringBuilder keywords = new StringBuilder();
        private static StringBuilder eventmsg = new StringBuilder();
        private static String TargetUserSid = "";
        private static String TargetUserName = "";
        private static String TargetUserInt = "";
        private static String TargetIp = "";
        private static String LogonType = "";
        private static Int64 _recordId = 0;
        private static StreamWriter ew = new StreamWriter(ConfigurationManager.AppSettings["ErrorLogPath"].ToString(), true, Encoding.UTF8);
        private static bool win2008 = false;

        internal static void Start()
        {
            // This is a Windows Sockets 2 error code.
            const int WSAETIMEDOUT = 10060;

            Socket serverSocket;
            System.Text.UTF8Encoding encoding = new System.Text.UTF8Encoding();


            string Query = String.Format("Select RecordNumber,SourceName,TimeGenerated,Category,CategoryString,ComputerName,EventCode,EventType,Type,Message from Win32_NTLogEvent Where Logfile = 'Security' and TimeGenerated > '" + ManagementDateTimeConverter.ToDmtfDateTime(DateTime.UtcNow.Subtract(TimeSpan.FromHours(5))) + "'");


            int numberOfEvents = 0;
            Random random = new Random();


            IPAddress ipAddress = IPAddress.Parse("127.0.0.1");
            //IPAddress ipAddress = Dns.GetHostAddresses(Dns.GetHostName())[int.Parse(ConfigurationManager.AppSettings["DnsHostNameIndex"].ToString())];
            if (ConfigurationManager.AppSettings["IpOverride"].ToString() != "1")
            {
                foreach (IPAddress ip in Dns.GetHostAddresses(Dns.GetHostName()))
                {
                    if (ip.AddressFamily != AddressFamily.InterNetworkV6 & !IPAddress.IsLoopback(ip) & ip.ToString().StartsWith("10."))
                    {
                        ipAddress = ip;
                    }
                }
            }
            else
            {
                ipAddress = IPAddress.Parse(ConfigurationManager.AppSettings["IpAddress"].ToString());
            }
            int _port = int.Parse(ConfigurationManager.AppSettings["OpenPort"]);

            bool stopped = false;

            IPEndPoint ipEndpoint = new IPEndPoint(ipAddress, _port);
            while (true)
            {

                // Create a socket and listen for incoming connections.
                using (Socket listenSocket = new Socket(
                    AddressFamily.InterNetwork, SocketType.Stream,
                    ProtocolType.Tcp))
                {
                    listenSocket.Bind(ipEndpoint);
                    listenSocket.Listen(1);

                    // Accept a connection and create a socket to handle it.
                    serverSocket = listenSocket.Accept();
                    //Console.WriteLine("Server is connected.\n");
                }
                #region eventlogreader path
                    try
                    {
                        string query;
                        if (_recordId != 0)
                        {
                            Query = String.Format("Select RecordNumber,SourceName,TimeGenerated,Category,CategoryString,ComputerName,EventCode,EventType,Type,Message from Win32_NTLogEvent Where Logfile = 'Security' and RecordNumber > " + _recordId);

                        }
                        else
                        {
                            Query = String.Format("Select RecordNumber,SourceName,TimeGenerated,Category,CategoryString,ComputerName,EventCode,EventType,Type,Message from Win32_NTLogEvent Where Logfile = 'Security' and TimeGenerated > '" + ManagementDateTimeConverter.ToDmtfDateTime(DateTime.Now.Subtract(TimeSpan.FromMinutes(5))) + "'");
                        }
                        // Query the log

                        ManagementObjectSearcher mos = new ManagementObjectSearcher(Query);
                        object o;
                        foreach (ManagementObject mo in mos.Get())
                        {

                            eventmsg.Append(mo["RecordNumber"] != null ? (mo["RecordNumber"]) : 1);
                            eventmsg.Append("|");
                            eventmsg.Append(ManagementDateTimeConverter.ToDateTime(mo["TimeGenerated"].ToString()).ToString());
                            eventmsg.Append("|");
                            eventmsg.Append(mo["SourceName"]);
                            eventmsg.Append("|");
                            eventmsg.Append(mo["Category"]);
                            eventmsg.Append("|");
                            eventmsg.Append(mo["CategoryString"]);
                            eventmsg.Append("|");
                            eventmsg.Append(mo["ComputerName"]);
                            eventmsg.Append("|");
                            eventmsg.Append(mo["EventCode"]);
                            eventmsg.Append("|");
                            eventmsg.Append(mo["EventType"]);
                            eventmsg.Append("|");
                            eventmsg.Append(mo["Type"]);
                            eventmsg.Append("|");
                            int idx = ((String)mo["Message"]).IndexOf("This event");
                            if (idx > -1)
                            {
                                eventmsg.Append(((String)mo["Message"]).Remove(idx - 1).Replace("\r\n", " "));

                            }
                            else
                            {
                                eventmsg.Append(((String)mo["Message"]).Replace("\r\n", " "));

                            }

                            eventmsg.Append("\n");
                            _recordId = System.Math.Max(_recordId,Convert.ToInt64(mo["RecordNumber"]));
 
                        

                        }
                    }
                        
                    catch (Exception e)
                    {
                        //TODO: need to reset eventmsg to 0 length string first
                        eventmsg.AppendFormat("{0}|{1}|{2}|{3}", "CollectorError", e.Message, e.InnerException, DateTime.Now);
                        eventmsg.Append("\n");

                       
                        
                        ////Console.WriteLine("Couldn't render event!");
                        ////Console.WriteLine("Exception: Event {0} may not have an XML representation \n\n", ++numberOfEvents);
                        //Console.WriteLine(TargetUserInt + "\n\r" + e);
                    }
                    try
                    {
                        int bytesSent = serverSocket.Send(encoding.GetBytes(eventmsg.ToString()), 0, eventmsg.Length, SocketFlags.None);
                        //Console.WriteLine(eventInstance.RecordId + " TargetUserInt " + TargetUserInt + " TargetUserSid " + TargetUserSid + " TargetUserName " + TargetUserName);
                    }
                    catch (Exception ex)
                    {


                    }
                    finally
                    {
                        eventmsg.Remove(0, eventmsg.Length);
                        serverSocket.Shutdown(SocketShutdown.Both);
                        //Console.WriteLine("Connection shut down.");
                        serverSocket.Close();

                        System.Threading.Thread.Sleep(8000);
                    }
                #endregion
  
 
                }// while close

            
    }

        internal static void Stop()
        {
            keywords = null;
            eventmsg = null;
            TargetUserSid = null;
            TargetUserName = null;
            TargetUserInt = null;

        }
    }
}
